package com.dx.architectureddd.common.task.config;

import com.dx.architectureddd.common.task.ScheduledTasks;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

/**
 * scheduler配置类
 *
 * @author xin.deng
 * @date 2023/10/14
 */
@Slf4j
@Configuration
public class ScheduledTaskRegistrar implements SchedulingConfigurer {

    private static org.springframework.scheduling.config.ScheduledTaskRegistrar scheduledTaskRegistrar;

    private static Set<Long> scheduledChannel = new HashSet<>();

    @Override
    public void configureTasks(org.springframework.scheduling.config.ScheduledTaskRegistrar taskRegistrar) {
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(10);
        taskScheduler.initialize();
        taskRegistrar.setTaskScheduler(taskScheduler);
        ScheduledTaskRegistrar.scheduledTaskRegistrar = taskRegistrar;
    }

    public static void addScheduledTask(ScheduledTasks runnable) {
        // 每个定时任务有一个唯一值用来标识该定时任务
        if (!scheduledChannel.contains(runnable.getTaskId())) {
            taskRegister(runnable);
            log.info(runnable.getTaskId() + " - 定时任务被添加");
        } else {
            log.info("任务已经存在，先移除");
            deleteSchedule(runnable.getTaskId());
            taskRegister(runnable);
            log.info(runnable.getTaskId() + " - 移除后，定时任务被添加");
        }
    }

    /**
     * 任务注册
     *
     * @param runnable @see
     * @see ScheduledTasks
     */
    private static void taskRegister(ScheduledTasks runnable) {
        // 避免原有的定时任务再次被添加到任务中重复执行
        scheduledTaskRegistrar.setTriggerTasks(new HashMap<>());
        scheduledTaskRegistrar.setCronTasks(new HashMap<>());
        scheduledTaskRegistrar.setFixedRateTasks(new HashMap<>());
        scheduledTaskRegistrar.setFixedDelayTasks(new HashMap<>());

        scheduledTaskRegistrar.addCronTask(runnable, runnable.getCronStr());
        // 当执行了后，上面的addCronTask才会生效
        scheduledTaskRegistrar.afterPropertiesSet();

        // 将其加入到缓存中标识该定时任务已经生成
        scheduledChannel.add(runnable.getTaskId());
    }

    /**
     * 删除定时任务
     *
     * @param taskId 任务唯一标识
     */
    public static void deleteSchedule(Long taskId) {
        if (scheduledChannel.contains(taskId)) {
            scheduledTaskRegistrar.getScheduledTasks().forEach(v -> {
                if (v.getTask().getRunnable() instanceof ScheduledTasks) {
                    ScheduledTasks tasks = (ScheduledTasks) v.getTask().getRunnable();
                    if (tasks.getTaskId().equals(taskId)) {
                        v.cancel();
                        scheduledChannel.remove(taskId);
                        log.info(taskId + " - 定时任务已被移除");
                    }
                }
            });
        }
    }
}
